﻿/**
* CRL
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using CRL.Core.Remoting.WorkConsole;
using TaskStatus = CRL.Core.Remoting.WorkConsole.TaskStatus;
using System.Collections.Concurrent;

namespace CRL.Core
{
    public class ThreadWork
    {
        Thread thread;
        static ConcurrentDictionary<string, ThreadWork> threads = new ConcurrentDictionary<string, ThreadWork>();
        public object Args;
        static IWorkManageClient workManage;
        bool canWork = true;
        string threadName;
        public static void SetWorkManage(IWorkManageClient _workManage = null)
        {
            workManage = _workManage;
            workManage.OnPauseWork = (workName) =>
            {
                threads.TryGetValue(workName,out var thread);
                if (thread != null)
                {
                    thread.Pause();
                    Console.WriteLine($"{DateTime.Now} {workName} pause");
                    workManage.UpdateWorkStatus(workName, WorkStatus.Pause);
                }
            };
            workManage.OnResumeWork = (workName) =>
            {
                threads.TryGetValue(workName, out var thread);
                if (thread != null)
                {
                    thread.Resume();
                    Console.WriteLine($"{DateTime.Now} {workName} resume");
                    workManage.UpdateWorkStatus(workName, WorkStatus.Runing);
                }
            };
            workManage.StartMonitor();
        }

        public void Start(string name, Func<bool> action, double second)
        {
            Start(name, (args) =>
             {
                 return action();
             }, second);
        }

        public void Start(string name, Func<object,bool> action, double second, bool randSleep = false)
        {
            if (second == 0)
            {
                throw new Exception("second不能为0");
            }
            var updateStatus = second >= 5;
            var workName = $"ThreadWork_{name}";
            threadName = workName;
            if (thread == null)
            {
                thread = new Thread(() =>
                {
                    CallContext.SetData("ThreadWorkCurrent", workName);
                    while (true)
                    {
                        if (canWork)
                        {
                            var sw = new System.Diagnostics.Stopwatch();
                            sw.Start();
                            string errorMsg = "";
                            try
                            {
                                if (updateStatus)
                                {
                                    workManage?.UpdateTaskStatus(workName, TaskStatus.Runing, 0, "");
                                }
                                action(Args);
                            }
                            catch (Exception ero)
                            {
                                errorMsg = ero.Message;
                                if (ero is ThreadAbortException)
                                {
                                    break;
                                }
                                Console.WriteLine("ThreadWork时发生错误" + ero);
                                EventLog.Log("ThreadWork时发生错误" + ero, "ThreadWork_" + name);
                            }
                            sw.Stop();
                            try
                            {
                                if (updateStatus)
                                {
                                    workManage?.UpdateTaskStatus(workName, TaskStatus.Wait, sw.ElapsedMilliseconds, errorMsg);
                                }
                            }
                            catch { }
                        }
                        var sleep = second;
                        if (randSleep && second > 5)
                        {
                            var n = (int)(second / 5);
                            sleep = new Random().Next((int)second - n * 2, (int)second + n * 2);
                            //Console.WriteLine($"{DateTime.Now} {name} working");
                        }
                        Thread.Sleep((int)(1000 * sleep));
                    }
                });
                threads.TryAdd(workName, this);
                if (updateStatus)
                {
                    workManage?.InitWork(new WorkDetail
                    {
                        WorkName = workName,
                        Repeat = TimeSpan.FromSeconds(second).ToString(),
                        WorkStatus = WorkStatus.Runing,
                        TaskStatus = TaskStatus.Wait,
                        HeartTime = DateTime.Now
                    });
                }
                thread.IsBackground = true;
                thread.Start();
                EventLog.Log(name + "启动", "ThreadWork");
            }
        }
        public void Pause()
        {
            canWork = false;
        }
        public void Resume()
        {
            canWork = true;
        }

        public void Stop()
        {
            if (thread != null)
            {
                thread.Abort();
            }
        }
        public static void StopAll()
        {
            foreach (var kv in threads)
            {
                var item = kv.Value;
                try
                {
                    item.Stop();
                }
                catch { }
            }
        }
    }
}
